package com.cmwa.scbp.business.postMaintenance.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;

import com.cmwa.scbp.base.constants.Constant;
import com.cmwa.scbp.base.exception.ValidateFailedException;
import com.cmwa.scbp.base.mvc.entity.Employee;
import com.cmwa.scbp.base.mvc.entity.Page;
import com.cmwa.scbp.base.mvc.entity.Result;
import com.cmwa.scbp.base.mvc.entity.SearchParam;
import com.cmwa.scbp.base.mvc.service.impl.BatchOperServiceImpl;
import com.cmwa.scbp.business.postMaintenance.dao.PostPersonnelChangeDao;
import com.cmwa.scbp.business.postMaintenance.dao.PostPersonnelInfoDao;
import com.cmwa.scbp.business.postMaintenance.entity.PostPersonnelChangeVo;
import com.cmwa.scbp.business.postMaintenance.entity.PostPersonnelInfoVo;
import com.cmwa.scbp.business.postMaintenance.service.PostPersonnelChangeService;
import com.cmwa.scbp.utils.DateUtils;
import com.cmwa.scbp.utils.SessionUtils;
import com.google.common.base.Joiner;

/**
 * 岗位人员变更表业务实现层
 * 
 * @author ex-sujh
 * @date 2019-02-22 10:46:12
 */
@Service
public class PostPersonnelChangeServiceImpl extends BatchOperServiceImpl implements PostPersonnelChangeService {
	
	private final ReentrantLock lock = new ReentrantLock();
	private static final Log log = LogFactory.getLog(PostPersonnelChangeServiceImpl.class);
	
	@Resource
	private PostPersonnelChangeDao postPersonnelChangeDao;
	@Resource
	private PostPersonnelInfoDao postPersonnelInfoDao;
	
		
	private final static String POST_PERSONNEL_CHANGE_BATACH_SAVE = "com.cmwa.scbp.business.postMaintenance.dao.PostPersonnelChangeDao.savePostPersonnelChange";
	private final static String POST_PERSONNEL_CHANGE_BATACH_UPDATE = "com.cmwa.scbp.business.postMaintenance.dao.PostPersonnelChangeDao.batchUpdatePersonnelChange";
	private final static String POST_PERSONNEL_INFO_BATACH_DELETE = "com.cmwa.scbp.business.postMaintenance.dao.PostPersonnelInfoDao.batchDeletePostPersonnelInfo";
	private final static String POST_PERSONNEL_INFO_BATACH_INSERT = "com.cmwa.scbp.business.postMaintenance.dao.PostPersonnelInfoDao.batchInsert";
	
	@Override
	public void insertPostPersonnelChange(PostPersonnelChangeVo postPersonnelChange) {
		postPersonnelChangeDao.insertPostPersonnelChange(postPersonnelChange);
	}
	
		
		
	@Override
	public void physicDeletePostPersonnelChangeById(String id) {
		postPersonnelChangeDao.physicDeletePostPersonnelChangeById(id);
	}
	
		
		
	@Override
	public void logicDeletePostPersonnelChangeById(String id) {
		postPersonnelChangeDao.logicDeletePostPersonnelChangeById(id);
	}
	
		
		
	@Override
	public void updatePostPersonnelChangeById(PostPersonnelChangeVo postPersonnelChange) {
		postPersonnelChangeDao.updatePostPersonnelChangeById(postPersonnelChange);
	}
	
		
		
	@Override
	public Page<PostPersonnelChangeVo> postPersonnelChangeListPage(SearchParam sp) {
		List<PostPersonnelChangeVo> items = postPersonnelChangeDao.postPersonnelChangeListPage(sp);
		return Page.create(items, sp.getStart(), sp.getLimit(), sp.getTotal());
	}
	
		
		
	@Override
	public PostPersonnelChangeVo getPostPersonnelChangeById(String id) {
		return postPersonnelChangeDao.getPostPersonnelChangeById(id);
	}
	
	@Override
	public List<Map<String, String>> queryResouceListByCondition(SearchParam sp) {
		Employee employee = SessionUtils.getEmployee();
		if (StringUtils.equals(employee.getEmpType(), "OUT")) {
			sp.getSp().put("empId", employee.getID());
			
		}
		String type = (String) sp.getSp().get("type");
		
		String oldPersonnelId = (String)sp.getSp().get("oldPersonnelId");
		List<String> list = Arrays.asList(oldPersonnelId.split(","));
		Collections.sort(list);
		sp.getSp().put("oldPersonnelId", Joiner.on("%").join(list));
		String resourceIds = (String) sp.getSp().get("resourceIds");
		if (StringUtils.isNotBlank(resourceIds)) {
			sp.getSp().put("resourceIds", Arrays.asList(resourceIds.split(",")));
		} else {
			sp.getSp().put("resourceIds", new ArrayList<>());
		}
		
		List<Map<String, String>> resourceMap = new ArrayList<>();
		if (StringUtils.equals(type, "SERIES_PRD")) {
			resourceMap = postPersonnelChangeDao.queryPrjListByCondition(sp);
		} else if (StringUtils.equals(type, "MANAGER")) {
			resourceMap = postPersonnelChangeDao.queryManagerListByCondition(sp);
		}
		
		return resourceMap;
	}
	
	@Override
	public void savePostPersonnelChange(PostPersonnelChangeVo postPersonnelChangeVo) throws Exception {
		// 加锁
		lock.lock();
		try {
			if (StringUtils.isBlank(postPersonnelChangeVo.getEffctiveDate()) || StringUtils.isBlank(postPersonnelChangeVo.getNewPersonnelId())
					|| StringUtils.isBlank(postPersonnelChangeVo.getResourceId()) || StringUtils.isBlank(postPersonnelChangeVo.getPostId())) {
				throw new ValidateFailedException("Params are null or empty");
			}
			List<PostPersonnelChangeVo> addList = new ArrayList<PostPersonnelChangeVo>();
			
			String empId = SessionUtils.getEmployee().getID();
			String postId = postPersonnelChangeVo.getPostId().split("&&")[0];
			String postRank = postPersonnelChangeVo.getPostId().split("&&")[1];
			String effectDate = postPersonnelChangeVo.getEffctiveDate();
			String newPersonnelId = postPersonnelChangeVo.getNewPersonnelId();
			String[] resourceIds = postPersonnelChangeVo.getResourceId().split(",");
			String remark = postPersonnelChangeVo.getRemark();
			
			PostPersonnelChangeVo changeVo = new PostPersonnelChangeVo();
			changeVo.setPostId(postId);
			changeVo.setResourceId(postPersonnelChangeVo.getResourceId());
			changeVo.setEffctiveDate(effectDate);
			Result<?> result = this.checkEffctiveDateUnique(changeVo);
			if (!result.isSuccess()) {
				throw new ValidateFailedException("已存在相同生效日的变更");
			}
			
			SearchParam sp = new SearchParam();
			sp.getSp().put("resourceId", Arrays.asList(postPersonnelChangeVo.getResourceId().split(",")));
			sp.getSp().put("postId", postId);
			sp.getSp().put("postRank", postRank);
			
			// 查询资源对应的人员列表
			List<PostPersonnelInfoVo> oldPersonnelIdsList = postPersonnelInfoDao.queryResourceIds(sp);
			Map<String, String> oldPersonnelIdsMap = new HashMap<String, String>();
			oldPersonnelIdsList.forEach(vo -> {
				oldPersonnelIdsMap.put(vo.getResourceId(), vo.getPersonnelId());
			});
			
			for (String resourceId : resourceIds) {
				String oldPersonnelId = oldPersonnelIdsMap.get(resourceId);
				
				PostPersonnelChangeVo vo = new PostPersonnelChangeVo();
				vo.setPostId(postId);
				vo.setResourceId(resourceId);
				vo.setNewPersonnelId(newPersonnelId);
				vo.setOldPersonnelId(oldPersonnelId);
				vo.setCreateId(empId);
				vo.setRemark(remark);
				vo.setEffctiveDate(effectDate);
				
				int isValid = DateUtils.compare(effectDate, DateUtils.getNowStr(DateUtils.DATE_FORMAT_yMd_EN), DateUtils.DATE_FORMAT_yMd_EN);
				vo.setHandleStatus(Constant.C_STATUS_Y);//生效
				if (isValid == 1) {
					//未来
					vo.setHandleStatus(Constant.C_STATUS_N);
				}
				addList.add(vo);
			}
			if (CollectionUtils.isNotEmpty(addList) && addList.size() > 0) {
				super.batchOperateData(PostPersonnelChangeServiceImpl.POST_PERSONNEL_CHANGE_BATACH_SAVE, addList, Constant.INT_FIFTY);
				this.batchUpdatePostPersonnelAndIsUse(addList, "insert");
			}
		} catch (Exception e) {
			throw new ValidateFailedException(e);
		} finally {
			// 确保任何情况下都解锁
			lock.unlock();
		}
	}
	
	@Override
	public Result<?> checkEffctiveDateUnique(PostPersonnelChangeVo postPersonnelChangeVo) {
		Result<?> result = new Result<PostPersonnelChangeVo>();
		result.setSuccess(true);
		StringBuffer existsResource = new StringBuffer(" ");
		String postRank = postPersonnelChangeVo.getPostRank();
		
		SearchParam sp = new SearchParam();
		sp.getSp().put("id", postPersonnelChangeVo.getId());
		sp.getSp().put("postRank", postRank);
		sp.getSp().put("postId", postPersonnelChangeVo.getPostId());
		sp.getSp().put("resourceId", Arrays.asList(postPersonnelChangeVo.getResourceId().split(",")));
		sp.getSp().put("effctiveDate", postPersonnelChangeVo.getEffctiveDate());
		
		List<PostPersonnelChangeVo> list = postPersonnelChangeDao.queryChangeByResourceIdAndPostId(sp);
		for (PostPersonnelChangeVo vo : list) {
			result.setSuccess(false);
			
			if (StringUtils.equals(postRank, "SERIES_PRD")) {
				existsResource.append(vo.getPrjSName()).append(" ");
			} else if (StringUtils.equals(postRank, "MANAGER")) {
				existsResource.append(vo.getCompanyName()).append(" ");
			}
		}
		result.setMessage(existsResource.toString());
		return result;
	}
	
	@Override
	public void updatePostPersonnelAndIsUse(PostPersonnelChangeVo postPersonnelChangeVo, String method) throws Exception {
		List<PostPersonnelChangeVo> updateIsUseList = new ArrayList<PostPersonnelChangeVo>();
		List<PostPersonnelInfoVo> delPostPersonnelInfoList = new ArrayList<>();
		List<PostPersonnelInfoVo> addPostPersonnelInfoList = new ArrayList<>();
		
		String empId = SessionUtils.getEmployee().getID() == null ? "system" : SessionUtils.getEmployee().getID();
		
		SearchParam sp = new SearchParam();
		String postId = null;
		String resourceId = null;
		if (postPersonnelChangeVo != null) {
			postId = postPersonnelChangeVo.getPostId();
			resourceId = postPersonnelChangeVo.getResourceId();
			sp.getSp().put("resourceIds", Arrays.asList(resourceId.split(",")));
		}
		sp.getSp().put("postId", postId);
		
		List<PostPersonnelChangeVo> list = postPersonnelChangeDao.queryInvalidList(sp);
		if (CollectionUtils.isEmpty(list) || list.size() <= 0) {
			log.error(String.format("updatePostPersonnelAndIsUse -> 未找到需要同步的岗位人员变更记录, postId: %s, resourceId: %s ", postId, resourceId));
			if (StringUtils.equals("delete", method) || StringUtils.equals("udpate", method)) {
				// 需删除的岗位人员数据
				PostPersonnelInfoVo postPersonnelInfoVo = new PostPersonnelInfoVo();
				postPersonnelInfoVo.setResourceId(resourceId);
				postPersonnelInfoVo.setPostId(postId);
				delPostPersonnelInfoList.add(postPersonnelInfoVo);
				
				if (StringUtils.isNotBlank(postPersonnelChangeVo.getOldPersonnelId())) {
					// 需新增的岗位人员的数据
					String[] personnelIds = postPersonnelChangeVo.getOldPersonnelId().split(",");
					for (String personnelId : personnelIds) {
						postPersonnelInfoVo = new PostPersonnelInfoVo();
						postPersonnelInfoVo.setResourceId(postPersonnelChangeVo.getResourceId());
						postPersonnelInfoVo.setPostId(postPersonnelChangeVo.getPostId());
						postPersonnelInfoVo.setPersonnelId(personnelId);
						postPersonnelInfoVo.setStatus(Constant.C_STATUS_C);
						postPersonnelInfoVo.setCreateId(empId);
						addPostPersonnelInfoList.add(postPersonnelInfoVo);
					}
				}
			} else {
				return;
			}
		}
		PostPersonnelChangeVo param = null;
		for (PostPersonnelChangeVo vo : list) {
			// 如果未同步，则需将变更人员同步至对应岗位中
			if (StringUtils.equals(Constant.CONSTANT_STRING_ZERO, vo.getIsUse())) {
				// 需重置变更记录的同步状态的数据
				param = new PostPersonnelChangeVo();
				param.setResourceId(vo.getResourceId());
				param.setIsUse(Constant.CONSTANT_STRING_ZERO);
				param.setPostId(vo.getPostId());
				param.setHandleStatus(Constant.C_STATUS_Y);
				param.setEffctiveDate(vo.getEffctiveDate());
				updateIsUseList.add(param);
				// 需更新同步状态为“已同步的数据”
				param = new PostPersonnelChangeVo();
				param.setId(vo.getId());
				param.setIsUse(Constant.CONSTANT_STRING_ONE);
				updateIsUseList.add(param);
				// 需删除的岗位人员数据
				PostPersonnelInfoVo postPersonnelInfoVo = new PostPersonnelInfoVo();
				postPersonnelInfoVo.setResourceId(vo.getResourceId());
				postPersonnelInfoVo.setPostId(vo.getPostId());
				delPostPersonnelInfoList.add(postPersonnelInfoVo);
				// 需新增的岗位人员的数据
				String[] personnelIds = vo.getNewPersonnelId().split(",");
				for (String personnelId : personnelIds) {
					postPersonnelInfoVo = new PostPersonnelInfoVo();
					postPersonnelInfoVo.setResourceId(vo.getResourceId());
					postPersonnelInfoVo.setPostId(vo.getPostId());
					postPersonnelInfoVo.setPersonnelId(personnelId);
					postPersonnelInfoVo.setStatus(Constant.C_STATUS_C);
					postPersonnelInfoVo.setCreateId(empId);
					addPostPersonnelInfoList.add(postPersonnelInfoVo);
				}
			}
		}
		if (CollectionUtils.isNotEmpty(updateIsUseList) && updateIsUseList.size() > 0) {
			super.batchOperateData(PostPersonnelChangeServiceImpl.POST_PERSONNEL_CHANGE_BATACH_UPDATE, updateIsUseList, Constant.INT_FIFTY);
		}
		if (CollectionUtils.isNotEmpty(delPostPersonnelInfoList) && delPostPersonnelInfoList.size() > 0) {
			super.batchOperateData(PostPersonnelChangeServiceImpl.POST_PERSONNEL_INFO_BATACH_DELETE, delPostPersonnelInfoList, Constant.INT_FIFTY);
		}
		if (CollectionUtils.isNotEmpty(addPostPersonnelInfoList) && addPostPersonnelInfoList.size() > 0) {
			super.batchOperateData(PostPersonnelChangeServiceImpl.POST_PERSONNEL_INFO_BATACH_INSERT, addPostPersonnelInfoList, Constant.INT_FIFTY);
		}
	}
	
	@Override
	public void batchUpdatePostPersonnelAndIsUse(List<PostPersonnelChangeVo> list, String method) throws Exception {
		for (PostPersonnelChangeVo vo : list) {
			this.updatePostPersonnelAndIsUse(vo, method);
		}
	}
	
	@Override
	public void deletePostPersonnelChange(String id) throws Exception {
		if (StringUtils.isBlank(id)) {
			throw new ValidateFailedException("Param is null or empty.");
		}
		PostPersonnelChangeVo queryPostPersonnelChange = postPersonnelChangeDao.getPostPersonnelChangeById(id);
		if (queryPostPersonnelChange == null || StringUtils.equals(Constant.C_STATUS_D, queryPostPersonnelChange.getStatus())) {
			throw new ValidateFailedException("该变更记录已被删除");
		}
		PostPersonnelChangeVo vo = new PostPersonnelChangeVo();
		vo.setId(id);
		vo.setModifyId(SessionUtils.getEmployee().getID());
		postPersonnelChangeDao.deletePostPersonnelChange(vo);
		this.updatePostPersonnelAndIsUse(queryPostPersonnelChange, "delete");
	}
}
